package com.maple.webrtc.ui

import android.os.Bundle
import android.text.TextUtils
import android.widget.Button
import android.widget.EditText
import android.widget.ListView
import androidx.appcompat.app.AppCompatActivity
import com.blankj.utilcode.util.NetworkUtils
import com.maple.webrtc.R
import com.maple.webrtc.app.Const
import com.maple.webrtc.core.PeerConnectionObserverAdapter
import com.maple.webrtc.core.SdpObserverAdapter
import com.maple.webrtc.socket.Client
import com.maple.webrtc.socket.EventCode
import com.maple.webrtc.socket.SocketType
import com.maple.webrtc.utils.ToastUtils
import com.maple.webrtc.utils.WebRTCUtils
import org.json.JSONObject
import org.webrtc.DefaultVideoDecoderFactory
import org.webrtc.EglBase
import org.webrtc.IceCandidate
import org.webrtc.MediaConstraints
import org.webrtc.PeerConnection
import org.webrtc.PeerConnection.RTCConfiguration
import org.webrtc.PeerConnectionFactory
import org.webrtc.RtpTransceiver
import org.webrtc.SessionDescription
import org.webrtc.SurfaceViewRenderer
import org.webrtc.VideoTrack
import org.webrtc.createCustomVideoEncoderFactory

class AppActivity : AppCompatActivity() {

    private var etIp: EditText? = null
    private var btnConnect: Button? = null
    private var lvList: ListView? = null
    private var btnStart: Button? = null
    private var remoteRenderer: SurfaceViewRenderer? = null

    private lateinit var peerConnectionFactory: PeerConnectionFactory
    private var peerConnection: PeerConnection? = null

    private val eglBaseContext = EglBase.create().eglBaseContext

    private val user: String by lazy {
        NetworkUtils.getIpAddressByWifi()
    }


    private val listAdapter: MessageAdapter by lazy {
        MessageAdapter(this)
    }

    private val callback: Client.Callback by lazy {
        object :Client.Callback {
            override fun onConnected(host: String, port: Int) {
                addItemList("已连接->${host}:${port}")
            }

            override fun onReceive(json: JSONObject) {
                addItemList("onReceive->${json}")
                val eventCode = json.getString("eventCode")
                if(eventCode.equals(EventCode.OFFER.name)) {
                    createAnswer(json)
                }
            }
        }
    }


    private val client: Client by lazy {
        Client(Const.SERVER_PORT).apply {
            this.setCallback(callback)
        }
    }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_app)
        etIp = findViewById(R.id.et_ip)
        lvList = findViewById(R.id.lv_list)
        btnConnect = findViewById(R.id.btn_connect)
        btnStart = findViewById(R.id.btn_start)
        remoteRenderer = findViewById(R.id.svr_remote_renderer)
        remoteRenderer?.init(eglBaseContext, null)
        remoteRenderer?.setMirror(false)
        lvList?.adapter = listAdapter
        btnConnect?.setOnClickListener {
            val host = etIp?.text.toString().trim()
            if(TextUtils.isEmpty(host)) {
                ToastUtils.showToast("请输入ip")
                return@setOnClickListener
            }
            client.connect(host)
        }
        btnStart?.setOnClickListener {
            val json = JSONObject()
            json.put("eventCode",EventCode.JOIN.name)
            json.put("user",user)
            client.send(json)
        }
        initRTC()
    }

    private fun initRTC() {
        val options = PeerConnectionFactory.Options()
        val encoderFactory = createCustomVideoEncoderFactory(eglBaseContext, true, true) { true }

        val decoderFactory = DefaultVideoDecoderFactory(eglBaseContext)
        peerConnectionFactory = PeerConnectionFactory
            .builder()
            .setOptions(options)
            .setVideoEncoderFactory(encoderFactory)
            .setVideoDecoderFactory(decoderFactory)
            .createPeerConnectionFactory()

        val rtcConfig: RTCConfiguration = WebRTCUtils.createRTCConfiguration()
        rtcConfig.sdpSemantics = PeerConnection.SdpSemantics.UNIFIED_PLAN

        peerConnection = peerConnectionFactory.createPeerConnection(rtcConfig, object : PeerConnectionObserverAdapter(SocketType.CLIENT.name) {

            override fun onIceCandidate(iceCandidate: IceCandidate?) {
                super.onIceCandidate(iceCandidate)
                iceCandidate?.let { candidate ->
                    val json = JSONObject()
                    json.put("eventCode",EventCode.ICE_CANDIDATE.name)
                    json.put("user",user)
                    json.put("sdpMLineIndex",candidate.sdpMLineIndex)
                    json.put("sdpMid",candidate.sdpMid)
                    json.put("candidate",candidate.sdp)
                    client.send(json)
                }
            }


            override fun onTrack(transceiver: RtpTransceiver?) {
                super.onTrack(transceiver)
                // 回调
                if (transceiver != null && transceiver.receiver.track() is VideoTrack) {
                    val videoTrack = transceiver.receiver.track() as VideoTrack?
                    videoTrack?.addSink(remoteRenderer)
                }
            }
        })
    }

    private fun createAnswer(json: JSONObject) {
        peerConnection?.let { peer ->
            val description = json.getString("sdp")
            // 将接收到的SDP描述解析为SessionDescription对象
            val offer = SessionDescription(SessionDescription.Type.OFFER, description)
            peer.setRemoteDescription(object :SdpObserverAdapter("setRemoteDescription") {
                override fun onSetSuccess() {
                    super.onSetSuccess()
                    peer.createAnswer(object :SdpObserverAdapter("createAnswer") {
                        override fun onCreateSuccess(sdp: SessionDescription?) {
                            super.onCreateSuccess(sdp)
                            if (sdp != null && sdp.type == SessionDescription.Type.ANSWER) {
                                peer.setLocalDescription(object :SdpObserverAdapter("setLocalDescription") {
                                    override fun onSetSuccess() {
                                        super.onSetSuccess()
                                        val answerJson = JSONObject()
                                        answerJson.put("eventCode",EventCode.ANSWER.name)
                                        answerJson.put("user",json.getString("user"))
                                        answerJson.put("type",sdp.type)
                                        answerJson.put("sdp",sdp.description)
                                        client.send(answerJson)
                                    }
                              },sdp)
                            }
                        }
                    }, MediaConstraints())
                }
            }, offer)
        }
    }


    private fun addItemList(item: String) {
        listAdapter.addItem(item)
        lvList?.smoothScrollToPosition(listAdapter.dataList.size - 1)
    }

    override fun onDestroy() {
        super.onDestroy()
        peerConnection?.let {
            it.dispose()
        }
        remoteRenderer?.release()

        client.close()
        peerConnectionFactory.dispose()
    }
}